ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
ADC.c
Go to the documentation of this file.
00001 
00016 #include "Compile_Options.h"
00017 #include "derivative.h"
00018 #include "ADC.h"
00019 #include <limits.h>
00020 /*
00021  ******************************************************************************
00022  * constants
00023  ******************************************************************************
00024  */
00026 const ADC_t catADCInstanceList[] = 
00027 {
00028   &ADC_0, &ADC_1
00029 };
00030 /*
00031  ******************************************************************************
00032  * Globals
00033  ******************************************************************************
00034  */
00036 uint16_t* gpu16ADCResults[(ADC_NO_MODULES * (ADC_CH_MAX + 1u))];
00038 uint16_t gau16ADCChToRead[ADC_NO_MODULES];
00039 
00040 /*
00041  ******************************************************************************
00042  * Function : u8fnADCConvert()
00043  ******************************************************************************
00044  */
00045 uint8_t u8fnADCConvert(const uint8_t cu8ADCInstance,
00046                              const uint8_t cu8ADCCh, uint16_t* pu16Result)
00047 {
00048   uint8_t u8Status;
00049   ADCChConfig_t tADCChConfig;
00050   
00051   /* Disable any on-going ADC conversion */
00052   u8Status = u8fnADCNormalConversionEnable(cu8ADCInstance, CLEAR);
00053   if(CLEAR == u8Status)
00054   {
00055     /* Configure ADC channel */
00056     tADCChConfig.P.ChIsrEn = TRUE;
00057     tADCChConfig.P.ChDMAEn = CLEAR;
00058     tADCChConfig.P.Instance = cu8ADCInstance;
00059     tADCChConfig.P.Channel = cu8ADCCh;
00060     u8Status = u8fnADCChannelConfig(&tADCChConfig, pu16Result);
00061     
00062     if(CLEAR == u8Status)
00063     {
00064       /* Trigger a conversion */
00065       u8Status = u8fnADCNormalConversionEnable(cu8ADCInstance, TRUE);
00066       /* We'll exit now. Result shall be ready when ADC is done. */
00067       /* If the ADC is in SCAN mode, no need to redo this */
00068     }
00069   }
00070   else
00071   {
00072     /* In this particular case, status is already set to something. */
00073   }
00074   return (u8Status);
00075 }
00076 /*
00077  ******************************************************************************
00078  * u8fnADCConfig
00079  ******************************************************************************
00080  */
00081 uint8_t u8fnADCConfig(uint8_t u8Instance, ADCConfig_t* ptADCConfig)
00082 {
00083   /* Declare local variables */
00084   uint8_t u8Status;
00085   ADC_t tMyADC;
00086   
00087   /* Init local variables */
00088   u8Status = CLEAR;
00089   tMyADC = catADCInstanceList[u8Instance];
00090   
00091   /* Verify that the selected instance is valid */
00092   if (CLEAR != tMyADC)
00093   {
00094     /* Clear any previous settings to go read a particular channel */
00095     gau16ADCChToRead[u8Instance] = CLEAR;
00096     
00097     /* Force any ongoing operation to stop */
00098     tMyADC->MCR.B.NSTART = CLEAR;
00099     
00100     /* Force the ADC into low power mode */
00101     tMyADC->MCR.B.PWDN = TRUE;
00102     
00103     /* Configure according to passed parameter tADCConfig */
00104     /* Start with general config */
00105     /* Enable or disable an existing result to be overwritten */
00106     tMyADC->MCR.B.OWREN = ptADCConfig->P.OverWriteEn;
00107     /* Choose which alignment will be used */
00108     tMyADC->MCR.B.WLSIDE = ptADCConfig->P.LeftAligned;
00109     /* Select between one-shot and scan modes */
00110     tMyADC->MCR.B.MODE = ptADCConfig->P.ScanModeEn;
00111     /* Enable or disable the Cross-triggering unit */
00112     tMyADC->MCR.B.CTUEN = ptADCConfig->P.CTUEn;
00113     /* Enable or disable the power-saving auto-clock shut-off */
00114     tMyADC->MCR.B.ACK0 = ptADCConfig->P.AutoClockEn;
00115     /* Select clocking speed (divide by half or not */
00116     tMyADC->MCR.B.ADCLKSEL = ptADCConfig->P.ClkSel;
00117     
00118     /* Also enable corresponding Isrs */
00119     tMyADC->IMR.B.MSKEOCTU = ptADCConfig->P.EOCTUIsrEn;
00120     tMyADC->IMR.B.MSKJEOC = ptADCConfig->P.JEOCIsrEn;
00121     tMyADC->IMR.B.MSKJECH = ptADCConfig->P.JEOCHIsrEn;
00122     tMyADC->IMR.B.MSKEOC = ptADCConfig->P.EOCIsrEn;
00123     tMyADC->IMR.B.MSKECH = ptADCConfig->P.EOCHIsrEn;
00124     /* If necessary, enable DMAs and define how they will be cleared */
00125     tMyADC->DMAE.B.DCLR = ptADCConfig->P.DMAClrOnRead;
00126     tMyADC->DMAE.B.DMAEN = ptADCConfig->P.DMAEn;
00127     
00128     /* Next, configure sampling speed for high-resolution channels   */
00129     /* Note that extended channels are not configured at all because */
00130     /* Pictus only uses these channels.                              */
00131     tMyADC->CTR[CLEAR].R = (uint32_t) (ptADCConfig->R.CTR);
00132     
00133     /* Force the ADC into idle mode */
00134     tMyADC->MCR.B.PWDN = CLEAR;
00135   }
00136   else
00137   {
00138     u8Status = ADC_ERR_BAD_INSTANCE;
00139   }
00140   
00141   return (u8Status);
00142 }
00143 /*
00144  ******************************************************************************
00145  * u8fnADCSelectRegIndex
00146  ******************************************************************************
00147  */
00148 static uint8_t u8fnADCSelectRegIndex(uint8_t u8Channel, uint16_t* pu16Mask)
00149 {
00150   *pu16Mask = (uint16_t)(BIT0 << (u8Channel % BITS_IN_32));
00151   
00152   return (u8Channel / BITS_IN_32);
00153 }
00154 /*
00155  ******************************************************************************
00156  * u8fnADCChannelConfig
00157  ******************************************************************************
00158  */
00159 uint8_t u8fnADCChannelConfig(const ADCChConfig_t* tADCChConfig,
00160     const uint16_t* pu16Results)
00161 {
00162   /* Declare local variables */
00163   uint8_t u8Status;
00164   uint16_t u16ChRegMask;
00165   uint8_t u8ChRegIndex;
00166   ADC_t tMyADC;
00167   
00168   /* Init local variables */
00169   u8Status = CLEAR;
00170   tMyADC = catADCInstanceList[(uint8_t) tADCChConfig->P.Instance];
00171   
00172   if(N_ELEMENTS(catADCInstanceList) > (uint8_t)tADCChConfig->P.Instance)
00173   {
00174     /* Make sure that the passed channel is a valid one */
00175     if (ADC_CH_MAX >= tADCChConfig->P.Channel)
00176     {
00177       /* Make sure that there's no on-going conversion */
00178       if (CLEAR == (ADC_ST_SAMPLE & tMyADC->MSR.B.ADCSTATUS))
00179       {
00180         /* Make sure the module is not in low power mode - force it ON */
00181         tMyADC->MCR.B.PWDN = CLEAR;
00182         
00183         /* Figure out what the mask is for this particular channel */
00184         u8ChRegIndex = u8fnADCSelectRegIndex(
00185             (uint8_t)tADCChConfig->P.Channel, (uint16_t*)&u16ChRegMask);
00186         
00187         /* Enable this channel */
00188         tMyADC->NCMR[u8ChRegIndex].R |= u16ChRegMask;
00189         
00190         /* Now take care of ISR according to settings */
00191         if (TRUE == tADCChConfig->P.ChIsrEn)
00192         {
00193           tMyADC->CIMR[u8ChRegIndex].R |= u16ChRegMask;
00194           /* Point the result to the right location */
00195           gpu16ADCResults[((uint8_t) tADCChConfig->P.Instance * (ADC_CH_MAX
00196               + 1u)) + tADCChConfig->P.Channel] = (uint16_t*)pu16Results;
00197         }
00198         else
00199         {
00200           tMyADC->CIMR[u8ChRegIndex].R &= ~u16ChRegMask;
00201         }
00202         
00203         /* Same thing for DMA */
00204         if (TRUE == tADCChConfig->P.ChDMAEn)
00205         {
00206           tMyADC->DMAR[u8ChRegIndex].R |= u16ChRegMask;
00207         }
00208         else
00209         {
00210           tMyADC->DMAR[u8ChRegIndex].R &= ~u16ChRegMask;
00211           
00212           /* If DMA is not enabled, it is a good idea to remember */
00213           /* that we're supposed to be reading it in case CIMR is */
00214           /* not set. We will do so next.                         */
00215           gau16ADCChToRead[(uint8_t)tADCChConfig->P.Instance]
00216               |= u16ChRegMask;
00217         }
00218       }
00219       else
00220       {
00221         u8Status = ADC_ERR_ONGOING_CONV;
00222       }
00223     }
00224     else
00225     {
00226       u8Status = ADC_ERR_INVALID_CH;
00227     }
00228   }
00229   else
00230   {
00231     u8Status = ADC_ERR_BAD_INSTANCE;
00232   }
00233   
00234   return (u8Status);
00235 }
00236 
00237 /*
00238  ******************************************************************************
00239  * u8fnADCReadChannel
00240  ******************************************************************************
00241  */
00242 uint8_t u8fnADCReadChannel(uint8_t u8Instance, uint8_t u8Channel,
00243     uint16_t* pu16ADCResult)
00244 {
00245   /* Declare local variables */
00246   uint8_t u8Status;
00247   ADC_t tMyADC;
00248   
00249   /* Init local variables */
00250   u8Status = CLEAR;
00251   tMyADC = catADCInstanceList[u8Instance];
00252   
00253   /* If we have a correct instance */
00254   if (N_ELEMENTS(catADCInstanceList) > u8Instance)
00255   {
00256     /* If we have valid data */
00257     if (TRUE == tMyADC->CDR[u8Channel].B.VALID)
00258     {
00259       /* Copy the data to the pointer */
00260       *pu16ADCResult = (uint16_t) tMyADC->CDR[u8Channel].B.CDATA;
00261     }
00262     else
00263     {
00264       /* We don't have valid data if we're here */
00265       u8Status = ADC_ERR_INVALID_RESULT;
00266     }
00267   }
00268   else
00269   {
00270     /* We are pointing somewhere else. Don't continue */
00271     u8Status = ADC_ERR_BAD_INSTANCE;
00272   }
00273   
00274   return (u8Status);
00275 }
00276 
00277 /*
00278  ******************************************************************************
00279  * u8fnADCStatus
00280  ******************************************************************************
00281  */
00282 uint8_t u8fnADCStatus(uint8_t u8Instance)
00283 {
00284   /* Declare local variables */
00285   uint8_t u8Status;
00286   
00287   u8Status = (uint8_t)(catADCInstanceList[u8Instance]->MSR.B.ADCSTATUS);
00288   
00289   return (u8Status);
00290 }
00291 /*
00292  ******************************************************************************
00293  * u8fnADNormalConversionEnable
00294  ******************************************************************************
00295  */
00296 uint8_t u8fnADCNormalConversionEnable(uint8_t u8Instance, uint8_t u8Enable)
00297 {
00298   /* Declare local variables */
00299   uint8_t u8Status;
00300   
00301   /* Init Local Variables */
00302   u8Status = CLEAR;
00303   
00304   /* Continue only if pointer is valid */
00305   if (N_ELEMENTS(catADCInstanceList) > u8Instance)
00306   {
00307     catADCInstanceList[u8Instance]->MCR.B.NSTART = (CLEAR < u8Enable);
00308   }
00309   else
00310   {
00311     /* We had an error */
00312     u8Status = ADC_ERR_BAD_INSTANCE;
00313   }
00314   return (u8Status);
00315 }
00316  /*
00317   ******************************************************************************
00318   * vfnADCEoCIsr
00319   ******************************************************************************
00320   */
00321  static void vfnADCEoCIsr(uint8_t u8Instance)
00322  {
00323    /* Declare local variables */
00324    ADC_t tMyADC;
00325    vuint8_t u8Counter;
00326    uint16_t u16ChannelsToRead;
00327       
00328    /* Init Local Variables */
00329    tMyADC = catADCInstanceList[u8Instance];
00330    u16ChannelsToRead = gau16ADCChToRead[u8Instance];
00331    
00332    switch (tMyADC->ISR.R)
00333    {
00334      case (ADC_ISR_EOCTU_MASK):
00335      {
00336         /* Something*/
00337         break;
00338      }
00339      case (ADC_ISR_JEOC_MASK):
00340      {
00341        /* Something */
00342        u8Counter = 1;
00343        break;
00344      }
00345      case (ADC_ISR_JECH_MASK):
00346      {
00347        /* Something */
00348        u8Counter = 8;
00349        break;
00350      }
00351      case (ADC_ISR_EOC_MASK):
00352      {
00353        u8Counter = 3;
00354        break;
00355      }
00356      case (ADC_ISR_EOC_MASK | ADC_ISR_ECH_MASK):
00357      {
00358        /* Clear interrupt flag for EOC */
00359        tMyADC->ISR.R |= ADC_ISR_EOC_MASK;
00360        /* Trickle down to the ECH case */
00361      }
00362      case (ADC_ISR_ECH_MASK):
00363      {
00364        for (u8Counter = CLEAR; u8Counter < BITS_IN_16; u8Counter++)
00365        {
00366          if(BIT0 & u16ChannelsToRead)
00367          {
00368            
00369            *gpu16ADCResults[(u8Instance * (ADC_CH_MAX + 1u)) + u8Counter] = (uint16_t)tMyADC->CDR[u8Counter].B.CDATA;
00370            
00371          }
00372          else
00373          {
00374            /* Don't do anything */
00375          }
00376          u16ChannelsToRead >>= 1u;
00377        }
00378        tMyADC->ISR.R |= ADC_ISR_ECH_MASK;
00379        break;
00380     }
00381     default:
00382     {
00383       /* Nothing happened */
00384     }
00385   };
00386     
00387   return;
00388 }
00389 /*
00390  ******************************************************************************
00391  * vfnADC0EoCIsr
00392  ******************************************************************************
00393  */
00394 void vfnADC0EoCIsr(void)
00395 {
00396   vfnADCEoCIsr(ADC_MODULE_0);
00397   return;
00398 }
00399 /*
00400  ******************************************************************************
00401  * vfnADC1EoCIsr
00402  ******************************************************************************
00403  */
00404 void vfnADC1EoCIsr(void)
00405 {
00406   vfnADCEoCIsr(ADC_MODULE_1);
00407   return;
00408 }
00409 /*
00410  ******************************************************************************
00411  * vfnADCErrIsr
00412  ******************************************************************************
00413  */
00414 static void vfnADCErrIsr(uint8_t u8Instance)
00415 {
00416   (void)u8Instance;
00417   return;
00418 }
00419 /*
00420  ******************************************************************************
00421  * vfnADC0ErrIsr
00422  ******************************************************************************
00423  */
00424 void vfnADC0ErrIsr(void)
00425 {
00426   vfnADCErrIsr(ADC_MODULE_0);
00427   return;
00428 }
00429 /*
00430  ******************************************************************************
00431  * vfnADC1ErrIsr
00432  ******************************************************************************
00433  */
00434 void vfnADC1ErrIsr(void)
00435 {
00436   vfnADCErrIsr(ADC_MODULE_1);
00437   return;
00438 }
00439 /*
00440  ******************************************************************************
00441  * vfnADCWatchDogIsr
00442  ******************************************************************************
00443  */
00444 static void vfnADCWatchDogIsr(uint8_t u8Instance)
00445 {
00446   (void)u8Instance;
00447   return;
00448 }
00449 /*
00450  ******************************************************************************
00451  * vfnADC0WatchDogIsr
00452  ******************************************************************************
00453  */
00454 void vfnADC0WatchDogIsr(void)
00455 {
00456   vfnADCWatchDogIsr(ADC_MODULE_0);
00457   return;
00458 }
00459 /*
00460  ******************************************************************************
00461  * vfnADC1EoCTUIsr
00462  ******************************************************************************
00463  */
00464 void vfnADC1WatchDogIsr(void)
00465 {
00466   vfnADCWatchDogIsr(ADC_MODULE_1);
00467   return;
00468 }
00469 /*
00470  ******************************************************************************
00471  *
00472  *  End of file.
00473  *
00474  ******************************************************************************
00475  */